package com.backend.system.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.backend.system.dao.entity.Dictionary;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;

import java.util.*;
import java.util.function.BiConsumer;

/**
 * <p>
 * 数据字典表 服务类
 * </p>
 *
 * @author back-manage
 * @since 2024-04-12
 */
public interface IDictionaryService extends IService<Dictionary> {

    default List<Dictionary> listChildrenById(Long dictId) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getParentId, dictId);
        return this.list(queryWrapper);
    }

    default List<Dictionary> listChildrenByDictKey(String dictKey) {
        Dictionary parentDictionary = getByDictKey(dictKey);
        if (parentDictionary == null) {
            return Collections.emptyList();
        }

        return this.listChildrenById(parentDictionary.getId());
    }

    default Dictionary getByDictKey(String dictKey) {
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dictionary::getDictKey, dictKey);
        return this.getBaseMapper().selectOne(queryWrapper);
    }

    /**
     * 依据ID查字典，并转换数据为树形
     *
     * @param id      id为负数，查所有数据；否则查对应ID、
     * @param name    字典名，如果传了，则模糊查询
     * @param dictKey 字典key，如果传了，则精准查询
     * @return 树形字典数据
     */
    default List<Tree<Long>> listDictionaryTree(Long id, String dictKey, String name) {
        Dictionary dictionary = new Dictionary();
        if (id >= 0) {
            dictionary.setId(id);
        }
        LambdaQueryWrapper<Dictionary> queryWrapper = new LambdaQueryWrapper<>();
        // 字典ID不为空，查对应的字典数据和其直接子级的字典数据
        queryWrapper.and(Objects.nonNull(dictionary.getId()), query -> {
            query.eq(Dictionary::getId, dictionary.getId()).or().eq(Dictionary::getParentId, dictionary.getId());
        });
        // 字典key不为空，需要拦截匹配字典key
        queryWrapper.eq(StrUtil.isNotBlank(dictKey), Dictionary::getDictKey, dictKey);
        // 字典name不为空，需要拦截模糊匹配字典name
        queryWrapper.like(StrUtil.isNotBlank(name), Dictionary::getName, name);

        // 查库
        List<Dictionary> dictionaryList = this.list(queryWrapper);
        if (CollUtil.isEmpty(dictionaryList)) {
            return Collections.emptyList();
        }

        long minId = dictionaryList.stream().mapToLong(Dictionary::getParentId).min().orElse(0L);
        // 转换为树形
        return dictionaryToTree(dictionaryList, minId, null);
    }


    default List<Tree<Long>> dictionaryToTree(List<Dictionary> dictionaryList, Long rootId, BiConsumer<Map<String, Object>, Dictionary> biConsumer) {
        if (CollUtil.isEmpty(dictionaryList)) {
            return Collections.emptyList();
        }

        List<TreeNode<Long>> treeNodes = new ArrayList<>();
        for (Dictionary dictionary : dictionaryList) {
            TreeNode<Long> treeNode = new TreeNode<>();
            treeNode.setId(dictionary.getId());
            treeNode.setName(dictionary.getName());
            treeNode.setParentId(dictionary.getParentId());
            treeNode.setWeight(dictionary.getWeight());
            Map<String, Object> extra = new LinkedHashMap<>();
            extra.put("dictKey", dictionary.getDictKey());
            extra.put("dictVal", dictionary.getDictVal());
            extra.put("status", dictionary.getStatus().getDesc());
            extra.put("createUser", dictionary.getCreateUser());
            extra.put("createUsername", dictionary.getCreateUsername());
            extra.put("createTime", dictionary.getCreateTime());
            extra.put("updateTime", dictionary.getUpdateTime());
            if (biConsumer != null) {
                biConsumer.accept(extra, dictionary);
            }
            treeNode.setExtra(extra);
            treeNodes.add(treeNode);
        }

        return TreeUtil.build(treeNodes, rootId);
    }


}
